home *** CD-ROM | disk | FTP | other *** search
/ The Utilities Experience / The Utilities Experience - Volume 1.iso / software / misc / o-z / x-windows / mesa-amiwin / src / osmesa.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-30  |  15.4 KB  |  646 lines

  1. /* $Id: osmesa.c,v 1.5 1995/11/03 17:40:00 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995  Brian Paul  (brianp@ssec.wisc.edu)
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25. $Log: osmesa.c,v $
  26.  * Revision 1.5  1995/11/03  17:40:00  brianp
  27.  * added casts for C++ compilation
  28.  *
  29.  * Revision 1.4  1995/10/30  15:32:58  brianp
  30.  * added mask argument to read_[color|index]_pixels functions
  31.  *
  32.  * Revision 1.3  1995/10/19  15:49:06  brianp
  33.  * changed clear_color and set_color arguments to GLubytes
  34.  * changed arguments to gl_new_context
  35.  *
  36.  * Revision 1.2  1995/10/13  22:41:58  brianp
  37.  * renamed index to set_index and color to set_color
  38.  * make index_mask and color_mask return GL_FALSE
  39.  *
  40.  * Revision 1.1  1995/10/12  17:00:03  brianp
  41.  * Initial revision
  42.  *
  43.  */
  44.  
  45.  
  46.  
  47. /*
  48.  * Off-Screen Mesa rendering / Rendering into client memory space
  49.  */
  50.  
  51.  
  52. #include <stdlib.h>
  53. #include <string.h>
  54. #include "GL/osmesa.h"
  55. #include "context.h"
  56. #include "dd.h"
  57. #include "macros.h"
  58. #include "xform.h"
  59.  
  60.  
  61. struct osmesa_context {
  62.    struct gl_context *gl_ctx;    /* The GL/Mesa context */
  63.    GLenum format;        /* either GL_RGBA or GL_COLOR_INDEX */
  64.    void *buffer;        /* the image buffer */
  65.    GLint width, height;        /* size of image buffer */
  66.    GLuint pixel;        /* current color index or RGBA pixel value */
  67.    GLuint clearpixel;        /* pixel for clearing the color buffer */
  68. };
  69.  
  70.  
  71.  
  72. static OSMesaContext Current = NULL;
  73.  
  74. static void setup_DD_pointers( void );
  75.  
  76.  
  77.  
  78. /*
  79.  * Create an Off-Screen Mesa rendering context.  The only attribute needed is
  80.  * an RGBA vs Color-Index mode flag.
  81.  *
  82.  * Input:  format - either GL_RGBA or GL_COLOR_INDEX
  83.  *         sharelist - specifies another OSMesaContext with which to share
  84.  *                     display lists.  NULL indicates no sharing.
  85.  * Return:  an OSMesaContext or 0 if error
  86.  */
  87. OSMesaContext OSMesaCreateContext( GLenum format, OSMesaContext sharelist )
  88. {
  89.    OSMesaContext ctx;
  90.  
  91.    if (format!=GL_RGBA && format!=GL_COLOR_INDEX) {
  92.       return NULL;
  93.    }
  94.  
  95.    ctx = (OSMesaContext) malloc( sizeof(struct osmesa_context) );
  96.    if (ctx) {
  97.       ctx->gl_ctx = gl_new_context( (format==GL_RGBA) ? GL_TRUE : GL_FALSE,
  98.                                     255.0, 255.0, 255.0, 255.0,
  99.                                     GL_FALSE,
  100.                                     sharelist ? sharelist->gl_ctx : NULL );
  101.       if (!ctx->gl_ctx) {
  102.          free(ctx);
  103.          return NULL;
  104.       }
  105. #ifdef FOO
  106.       ctx->gl_ctx->RGBAflag = (format==GL_RGBA);
  107.       ctx->gl_ctx->RedScale = 255.0;
  108.       ctx->gl_ctx->GreenScale = 255.0;
  109.       ctx->gl_ctx->BlueScale = 255.0;
  110.       ctx->gl_ctx->AlphaScale = 255.0;
  111.       ctx->gl_ctx->Color.DrawBuffer = GL_FRONT;
  112.       ctx->gl_ctx->Pixel.ReadBuffer = GL_FRONT;
  113. #endif
  114.       ctx->format = format;
  115.       ctx->buffer = NULL;
  116.       ctx->width = 0;
  117.       ctx->height = 0;
  118.       ctx->pixel = 0;
  119.       ctx->clearpixel = 0;
  120.    }
  121.    return ctx;
  122. }
  123.  
  124.  
  125.  
  126. /*
  127.  * Destroy an Off-Screen Mesa rendering context.
  128.  *
  129.  * Input:  ctx - the context to destroy
  130.  */
  131. void OSMesaDestroyContext( OSMesaContext ctx )
  132. {
  133.    if (ctx) {
  134.       gl_destroy_context( ctx->gl_ctx );
  135.       free( ctx );
  136.    }
  137. }
  138.  
  139.  
  140.  
  141. /*
  142.  * Bind an OSMesaContext to an image buffer.  The image buffer is just a
  143.  * block of memory which the client provides.  Its size must be at least
  144.  * as large as width*height*sizeof(type).  Its address should be a multiple
  145.  * of 4 if using RGBA mode.
  146.  *
  147.  * Image data is stored in the order of glDrawPixels:  row-major order
  148.  * with the lower-left image pixel stored in the first array position
  149.  * (ie. bottom-to-top).
  150.  *
  151.  * Since the only type initially supported is GL_UNSIGNED_BYTE, if the
  152.  * context is in RGBA mode, each pixel will be stored as a 4-byte RGBA
  153.  * value.  If the context is in color indexed mode, each pixel will be
  154.  * stored as a 1-byte value.
  155.  *
  156.  * If the context's viewport hasn't been initialized yet, it will now be
  157.  * initialized to (0,0,width,height).
  158.  *
  159.  * Input:  ctx - the rendering context
  160.  *         buffer - the image buffer memory
  161.  *         type - data type for pixel components, only GL_UNSIGNED_BYTE
  162.  *                supported now
  163.  *         width, height - size of image buffer in pixels, at least 1
  164.  * Return:  GL_TRUE if success, GL_FALSE if error because of invalid ctx,
  165.  *          invalid buffer address, type!=GL_UNSIGNED_BYTE, width<1, height<1,
  166.  *          width>internal limit or height>internal limit.
  167.  */
  168. GLboolean OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type,
  169.                              GLsizei width, GLsizei height )
  170. {
  171.    if (!ctx || !buffer || type!=GL_UNSIGNED_BYTE
  172.        || width<1 || height<1 || width>MAX_WIDTH || height>MAX_HEIGHT) {
  173.       return GL_FALSE;
  174.    }
  175.  
  176.    gl_set_context( ctx->gl_ctx );
  177.  
  178.    ctx->buffer = buffer;
  179.    ctx->width = width;
  180.    ctx->height = height;
  181.  
  182.    setup_DD_pointers();
  183.  
  184.    Current = ctx;
  185.  
  186.    /* init viewport */
  187.    if (ctx->gl_ctx->Viewport.Width==0) {
  188.       /* initialize viewport and scissor box to buffer size */
  189.       gl_viewport( 0, 0, width, height );
  190.       CC.Scissor.X = 0;
  191.       CC.Scissor.Y = 0;
  192.       CC.Scissor.Width = width;
  193.       CC.Scissor.Height = height;
  194.    }
  195.  
  196.    return GL_TRUE;
  197. }
  198.  
  199.  
  200.  
  201.  
  202. /**********************************************************************/
  203. /*** Device Driver Functions                                        ***/
  204. /**********************************************************************/
  205.  
  206.  
  207. static void finish( void )
  208. {
  209.    /*NOP*/
  210. }
  211.  
  212.  
  213.  
  214. static void flush( void )
  215. {
  216.    /*NOP*/
  217. }
  218.  
  219.  
  220.  
  221. static GLboolean set_buffer( GLenum mode )
  222. {
  223.    if (mode==GL_FRONT) {
  224.       return GL_TRUE;
  225.    }
  226.    else {
  227.       return GL_FALSE;
  228.    }
  229. }
  230.  
  231.  
  232. static void clear_index( GLuint index )
  233. {
  234.    Current->clearpixel = index;
  235. }
  236.  
  237.  
  238.  
  239. static void clear_color( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
  240. {
  241.    /* This trick facilitates big & little endian */
  242.    GLubyte *clr = (GLubyte *) &Current->clearpixel;
  243.    clr[0] = r;
  244.    clr[1] = g;
  245.    clr[2] = b;
  246.    clr[3] = a;
  247. }
  248.  
  249.  
  250.  
  251. static void clear( GLboolean all, GLint x, GLint y, GLint width, GLint height )
  252. {
  253.    if (Current->format==GL_RGBA) {
  254.       if (all) {
  255.          /* Clear whole RGBA buffer */
  256.          GLuint i, n, *ptr4;
  257.          n = Current->width * Current->height;
  258.          ptr4 = (GLuint *) Current->buffer;
  259.          for (i=0;i<n;i++) {
  260.             *ptr4++ = Current->clearpixel;
  261.          }
  262.       }
  263.       else {
  264.          /* Clear part of RGBA buffer */
  265.          GLuint i, j;
  266.          for (i=0;i<height;i++) {
  267.             GLuint *ptr4 = (GLuint *) (Current->buffer) + Current->width * (y+i) + x;
  268.             for (j=0;j<width;j++) {
  269.                *ptr4++ = Current->clearpixel;
  270.             }
  271.          }
  272.       }
  273.    }
  274.    else {
  275.       if (all) {
  276.          /* Clear whole CI buffer */
  277.          MEMSET(Current->buffer, Current->clearpixel, Current->width*Current->height);
  278.       }
  279.       else {
  280.          /* Clear part of CI buffer */
  281.          GLuint i, j;
  282.          for (i=0;i<height;i++) {
  283.             GLubyte *ptr1 = (GLubyte *) (Current->buffer) + Current->width * (y+i) + x;
  284.             for (j=0;j<width;j++) {
  285.                *ptr1++ = Current->clearpixel;
  286.             }
  287.          }
  288.       }
  289.    }
  290. }
  291.  
  292.  
  293.  
  294. static void set_index( GLuint index )
  295. {
  296.    Current->pixel = index;
  297. }
  298.  
  299.  
  300.  
  301. static GLboolean index_mask( GLuint mask )
  302. {
  303.    return GL_FALSE;
  304. }
  305.  
  306.  
  307.  
  308. static void set_color( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
  309. {
  310.    /* This trick facilitates big & little endian */
  311.    GLubyte *clr = (GLubyte *) &Current->pixel;
  312.    clr[0] = r;
  313.    clr[1] = g;
  314.    clr[2] = b;
  315.    clr[3] = a;
  316. }
  317.  
  318.  
  319. static GLboolean color_mask( GLboolean rmask, GLboolean gmask,
  320.                              GLboolean bmask, GLboolean amask )
  321. {
  322.    return GL_FALSE;
  323. }
  324.  
  325.  
  326.  
  327. static GLboolean logicop( GLenum mode )
  328. {
  329.    if (mode==GL_COPY) {
  330.       return GL_TRUE;
  331.    }
  332.    else {
  333.       return GL_FALSE;
  334.    }
  335. }
  336.  
  337.  
  338. static void dither( GLboolean enable )
  339. {
  340.    /* NOP, never dither */
  341. }
  342.  
  343.  
  344. static void buffer_size( GLuint *width, GLuint *height, GLuint *depth )
  345. {
  346.    *width = Current->width;
  347.    *height = Current->height;
  348.    *depth = 8;
  349. }
  350.  
  351.  
  352.  
  353. /*
  354.  * Useful macros:
  355.  */
  356. #define OFFSET(X,Y)         ((Y) * Current->width + (X))
  357. #define PACK_RGBA(R,G,B,A)  (((R) << 24) | ((G) << 16) | ((B) << 8) | (A))
  358. #define PACK_ABGR(R,G,B,A)  (((A) << 24) | ((B) << 16) | ((G) << 8) | (R))
  359.  
  360.  
  361.  
  362.  
  363. static void write_RGBA_span( GLuint n, GLint x, GLint y,
  364.                              const GLubyte red[], const GLubyte green[],
  365.                  const GLubyte blue[], const GLubyte alpha[],
  366.                  const GLubyte mask[] )
  367. {
  368.    GLuint *ptr4 = (GLuint *) Current->buffer + OFFSET(x,y);
  369.    GLuint i;
  370.    if (mask) {
  371.       for (i=0;i<n;i++,ptr4++) {
  372.          if (mask[i]) {
  373.             *ptr4 = PACK_RGBA( red[i], green[i], blue[i], alpha[i] );
  374.          }
  375.       }
  376.    }
  377.    else {
  378.       for (i=0;i<n;i++,ptr4++) {
  379.          *ptr4 = PACK_RGBA( red[i], green[i], blue[i], alpha[i] );
  380.       }
  381.    }
  382. }
  383.  
  384.  
  385.  
  386. static void write_ABGR_span( GLuint n, GLint x, GLint y,
  387.                  const GLubyte red[], const GLubyte green[],
  388.                              const GLubyte blue[], const GLubyte alpha[],
  389.                  const GLubyte mask[] )
  390. {
  391.    GLuint *ptr4 = (GLuint *) Current->buffer + OFFSET(x,y);
  392.    GLuint i;
  393.    if (mask) {
  394.       for (i=0;i<n;i++,ptr4++) {
  395.          if (mask[i]) {
  396.             *ptr4 = PACK_ABGR( red[i], green[i], blue[i], alpha[i] );
  397.          }
  398.       }
  399.    }
  400.    else {
  401.       for (i=0;i<n;i++,ptr4++) {
  402.          *ptr4 = PACK_ABGR( red[i], green[i], blue[i], alpha[i] );
  403.       }
  404.    }
  405. }
  406.  
  407.  
  408.  
  409. static void write_monocolor_span( GLuint n, GLint x, GLint y,
  410.                   const GLubyte mask[] )
  411. {
  412.    GLuint *ptr4 = (GLuint *) Current->buffer + OFFSET(x,y);
  413.    GLuint i;
  414.    for (i=0;i<n;i++,ptr4++) {
  415.       if (mask[i]) {
  416.          *ptr4 = Current->pixel;
  417.       }
  418.    }
  419. }
  420.  
  421.  
  422.  
  423. static void write_RGBA_pixels( GLuint n, const GLint x[], const GLint y[],
  424.                                const GLubyte red[], const GLubyte green[],
  425.                    const GLubyte blue[], const GLubyte alpha[],
  426.                    const GLubyte mask[] )
  427. {
  428.    GLuint i;
  429.    for (i=0;i<n;i++) {
  430.       if (mask[i]) {
  431.          GLuint *ptr4 = (GLuint *) Current->buffer + OFFSET(x[i],y[i]);
  432.          *ptr4 = PACK_RGBA( red[i], green[i], blue[i], alpha[i] );
  433.       }
  434.    }
  435. }
  436.  
  437.  
  438.  
  439. static void write_ABGR_pixels( GLuint n, const GLint x[], const GLint y[],
  440.                                const GLubyte red[], const GLubyte green[],
  441.                    const GLubyte blue[], const GLubyte alpha[],
  442.                    const GLubyte mask[] )
  443. {
  444.    GLuint i;
  445.    for (i=0;i<n;i++) {
  446.       if (mask[i]) {
  447.          GLuint *ptr4 = (GLuint *) Current->buffer + OFFSET(x[i],y[i]);
  448.          *ptr4 = PACK_ABGR( red[i], green[i], blue[i], alpha[i] );
  449.       }
  450.    }
  451. }
  452.  
  453.  
  454.  
  455. static void write_monocolor_pixels( GLuint n, const GLint x[], const GLint y[],
  456.                     const GLubyte mask[] )
  457. {
  458.    GLuint i;
  459.    for (i=0;i<n;i++) {
  460.       if (mask[i]) {
  461.          GLuint *ptr4 = (GLuint *) Current->buffer + OFFSET(x[i],y[i]);
  462.          *ptr4 = Current->pixel;
  463.       }
  464.    }
  465. }
  466.  
  467.  
  468.  
  469. static void write_index_span( GLuint n, GLint x, GLint y, const GLuint index[],
  470.                   const GLubyte mask[] )
  471. {
  472.    GLubyte *ptr1 = (GLubyte *) Current->buffer + OFFSET(x,y);
  473.    GLuint i;
  474.    for (i=0;i<n;i++,ptr1++) {
  475.       if (mask[i]) {
  476.          *ptr1 = (GLubyte) index[i];
  477.       }
  478.    }
  479. }
  480.  
  481.  
  482.  
  483. static void write_monoindex_span( GLuint n, GLint x, GLint y,
  484.                   const GLubyte mask[] )
  485. {
  486.    GLubyte *ptr1 = (GLubyte *) Current->buffer + OFFSET(x,y);
  487.    GLuint i;
  488.    for (i=0;i<n;i++,ptr1++) {
  489.       if (mask[i]) {
  490.          *ptr1 = (GLubyte) Current->pixel;
  491.       }
  492.    }
  493. }
  494.  
  495.  
  496.  
  497. static void write_index_pixels( GLuint n, const GLint x[], const GLint y[],
  498.                     const GLuint index[], const GLubyte mask[] )
  499. {
  500.    GLuint i;
  501.    for (i=0;i<n;i++) {
  502.       if (mask[i]) {
  503.          GLubyte *ptr1 = (GLubyte *) Current->buffer + OFFSET(x[i],y[i]);
  504.          *ptr1 = (GLubyte) index[i];
  505.       }
  506.    }
  507. }
  508.  
  509.  
  510.  
  511. static void write_monoindex_pixels( GLuint n, const GLint x[], const GLint y[],
  512.                     const GLubyte mask[] )
  513. {
  514.    GLuint i;
  515.    for (i=0;i<n;i++) {
  516.       if (mask[i]) {
  517.          GLubyte *ptr1 = (GLubyte *) Current->buffer + OFFSET(x[i],y[i]);
  518.          *ptr1 = (GLubyte) Current->pixel;
  519.       }
  520.    }
  521. }
  522.  
  523.  
  524.  
  525. static void read_index_span( GLuint n, GLint x, GLint y, GLuint index[] )
  526. {
  527.    GLuint i;
  528.    GLubyte *ptr1 = (GLubyte *) Current->buffer + OFFSET(x,y);
  529.    for (i=0;i<n;i++,ptr1++) {
  530.       index[i] = (GLuint) *ptr1;
  531.    }
  532. }
  533.  
  534.  
  535. static void read_color_span( GLuint n, GLint x, GLint y,
  536.                              GLubyte red[], GLubyte green[],
  537.                  GLubyte blue[], GLubyte alpha[] )
  538. {
  539.    GLuint i;
  540.    GLubyte *ptr1 = (GLubyte *) Current->buffer + OFFSET(x,y) * 4;
  541.    for (i=0;i<n;i++) {
  542.       red[i]   = *ptr1++;
  543.       green[i] = *ptr1++;
  544.       blue[i]  = *ptr1++;
  545.       alpha[i] = *ptr1++;
  546.    }
  547. }
  548.  
  549.  
  550. static void read_index_pixels( GLuint n, const GLint x[], const GLint y[],
  551.                    GLuint index[], const GLubyte mask[] )
  552. {
  553.    GLuint i;
  554.    for (i=0;i<n;i++) {
  555.       if (mask[i] ) {
  556.          GLubyte *ptr1 = (GLubyte *) Current->buffer + OFFSET(x[i],y[i]);
  557.          index[i] = (GLuint) *ptr1;
  558.       }
  559.    }
  560. }
  561.  
  562.  
  563. static void read_color_pixels( GLuint n, const GLint x[], const GLint y[],
  564.                    GLubyte red[], GLubyte green[],
  565.                    GLubyte blue[], GLubyte alpha[],
  566.                                const GLubyte mask[] )
  567. {
  568.    GLuint i;
  569.    for (i=0;i<n;i++) {
  570.       if (mask[i]) {
  571.          GLubyte *ptr1 = (GLubyte *) Current->buffer + OFFSET(x[i],y[i]) * 4;
  572.          red[i]   = *ptr1++;
  573.          green[i] = *ptr1++;
  574.          blue[i]  = *ptr1++;
  575.          alpha[i] = *ptr1;
  576.       }
  577.    }
  578. }
  579.  
  580.  
  581. static points_func choose_points_function( void )
  582. {
  583.    /* No accelerated points functions */
  584.    return NULL;
  585. }
  586.  
  587. static line_func choose_line_function( void )
  588. {
  589.    /* No accelerated line functions */
  590.    return NULL;
  591. }
  592.  
  593. static polygon_func choose_polygon_function( void )
  594. {
  595.    /* No accelerated polygon functions */
  596.    return NULL;
  597. }
  598.  
  599.  
  600.  
  601. static void setup_DD_pointers( void )
  602. {
  603.    GLuint i4 = 1;
  604.    GLubyte *i1 = (GLubyte *) &i4;
  605.    GLint little_endian = *i1;
  606.  
  607.    DD.finish = finish;
  608.    DD.flush = flush;
  609.    DD.set_buffer = set_buffer;
  610.    DD.color = set_color;
  611.    DD.index = set_index;
  612.    DD.clear_index = clear_index;
  613.    DD.clear_color = clear_color;
  614.    DD.clear = clear;
  615.    DD.index_mask = index_mask;
  616.    DD.color_mask = color_mask;
  617.    DD.logicop = logicop;
  618.    DD.dither = dither;
  619.  
  620.    DD.buffer_size = buffer_size;
  621.  
  622.    DD.get_points_func = choose_points_function;
  623.    DD.get_line_func = choose_line_function;
  624.    DD.get_polygon_func = choose_polygon_function;
  625.  
  626.    if (little_endian) {
  627.       DD.write_color_span = write_ABGR_span;
  628.       DD.write_color_pixels = write_ABGR_pixels;
  629.    }
  630.    else {
  631.       DD.write_color_span = write_RGBA_span;
  632.       DD.write_color_pixels = write_RGBA_pixels;
  633.    }
  634.    DD.write_index_span = write_index_span;
  635.    DD.write_monocolor_span = write_monocolor_span;
  636.    DD.write_monoindex_span = write_monoindex_span;
  637.    DD.write_index_pixels = write_index_pixels;
  638.    DD.write_monocolor_pixels = write_monocolor_pixels;
  639.    DD.write_monoindex_pixels = write_monoindex_pixels;
  640.  
  641.    DD.read_color_span = read_color_span;
  642.    DD.read_index_span = read_index_span;
  643.    DD.read_color_pixels = read_color_pixels;
  644.    DD.read_index_pixels = read_index_pixels;
  645. }
  646.